home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
libs
/
hobbes3
/
rect.asm
< prev
next >
Wrap
Assembly Source File
|
1992-08-26
|
23KB
|
675 lines
include hobbes.inc
include extrn.inc
.DATA
; Plane masks for clipping left and right edges of rectangle
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 00fh,001h,003h,007h
.CODE
;----------------------------------------------------------------------------
; void RectangleFillAligned(int x0, int y0, int x1, int y1, COLOR);
;
public _RectangleFillAligned
_RectangleFillAligned proc
ARG X0, Y0, X1, Y1, COLOR
push bp
mov bp,sp
push ds
mov ax,@data
mov ds,ax
mov es,_ModeX_Segment ; point ES:DI to the first rectangle pixel's address
push si
push di
mov dx,SC_INDEX ; set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
inc dx ; point DX to the SC Data register
mov al,0fh ; write to all planes
out dx,al ; set the mask
cld
mov di,Y0
shl di,1 ; address of the row offset word
mov di,word ptr _RowOffset[di]
mov ax,X0
shr ax,2 ; X/4 = offset of pixel in scan line
add di,ax ; final offset of pixel in page
mov cx,X1 ; calculate # of addresses across rect
mov bx,X0
and bx,not 011b
sub cx,bx
shr cx,2 ; # of addresses across box to fill - 1
inc cx ; # of addresses across box to fill
mov si,cx ; save a copy in SI
mov bx,Y1
sub bx,Y0 ; BX = height of rectangle - 1
mov al,byte ptr COLOR ; color with which to fill
mov ah,al
mov bp,_Virtual_Width_Addr ; stack frame isn't needed any more
sub bp,cx ; distance from end of one scan line to start of next
@@BoxAligned_RowsLoop:
shr cx,1 ; get the number of pixel pairs
rep stosw ; draw the middle addresses eight pixels apiece
adc cx,0 ; odd number of pixels?
rep stosb ; rep used to draw the last pixel ONLY if necessary
add di,bp ; point to the start of the next scan line of
; the rectangle
mov cx,si ; retrieve width in addresses
dec bx ; count down scan lines
jnl @@BoxAligned_RowsLoop
@@BoxAligned_Done:
pop di
pop si
pop ds
pop bp
ret
_RectangleFillAligned endp
;----------------------------------------------------------------------------
; void RectangleFill(int StartX, int StartY, int EndX, int EndY, COLOR);
public _RectangleFill
_RectangleFill proc far
ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Color:WORD
push bp
mov bp,sp
push si
push di
push ds
mov ax,@data
mov ds,ax
cld
mov ax,_Virtual_Width_Addr
mul StartY ;offset in page of top rectangle scan line
mov di,StartX
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,_Display_Offset ;offset of first rectangle pixel in
; display memory
mov ax,_ModeX_Segment ;point ES:DI to the first rectangle
mov es,ax ; pixel's address
mov dx,SC_INDEX ;set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
inc dx ;point DX to the SC Data register
mov si,StartX
and si,0003h ;look up left edge plane mask
mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
mov si,EndX
and si,0003h ;look up right edge plane
mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
mov cx,EndX ;calculate # of addresses across rect
mov si,StartX
cmp cx,si
jle @@FillDone ;skip if 0 or negative width
dec cx
and si,not 011b
sub cx,si
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one byte to draw
and bh,bl ;there's only one byte, so combine the left
; and right edge clip masks
@@MasksSet:
mov si,EndY
sub si,StartY ;BX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov ah,byte ptr Color ;color with which to fill
mov bp,_Virtual_Width_Addr ;stack frame isn't needed any more
sub bp,cx ;distance from end of one scan line to start
dec bp ; of next
@@FillRowsLoop:
push cx ;remember width in addresses - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the left edge
dec cx ;count off left edge byte
js @@FillLoopBottom ;that's the only byte
jz @@DoRightEdge ;there are only two bytes
mov al,00fh ;middle addresses are drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
mov al,ah ;put color in AL
rep stosb ;draw the middle addresses four pixels apiece
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the right edge
@@FillLoopBottom:
add di,bp ;point to the start of the next scan line of
; the rectangle
pop cx ;retrieve width in addresses - 1
dec si ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
pop ds
pop di
pop si
pop bp
ret
_RectangleFill endp
;----------------------------------------------------------------------------
; void RectangleFillClip(int StartX, int StartY, int EndX, int EndY, COLOR);
public _RectangleFillClip
_RectangleFillClip proc far
ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Color:WORD
push bp
mov bp,sp
push si
push di
push ds
mov ax,@data
mov ds,ax
; clip it
; yeah, it's may be kinda cheezy, but it's still fairly quick
; (plus, it took about 5min :-])
@@_ClipLeft:
mov ax, StartX
cmp ax, _ClipLeft
jg @@_ClipRight
mov ax, _ClipLeft
mov StartX,ax
@@_ClipRight:
mov ax, EndX
cmp ax, _ClipRight
jle @@_ClipTop
mov ax, _ClipRight
mov EndX, ax
@@_ClipTop:
mov ax, StartY
cmp ax, _ClipTop
jg @@_ClipBottom
mov ax, _ClipTop
mov StartY, ax
@@_ClipBottom:
mov ax, EndY
cmp ax, _ClipBottom
jle @@ClipDone
mov ax, _ClipBottom
mov EndY, ax
@@ClipDone:
cld
mov di,StartY
shl di,1
mov ax,word ptr _RowOffset[di]
mov di,StartX
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,_Display_Offset ;offset of first rectangle pixel in
; display memory
mov ax,_ModeX_Segment ;point ES:DI to the first rectangle
mov es,ax ; pixel's address
mov dx,SC_INDEX ;set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
inc dx ;point DX to the SC Data register
mov si,StartX
and si,0003h ;look up left edge plane mask
mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
mov si,EndX
and si,0003h ;look up right edge plane
mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
mov cx,EndX ;calculate # of addresses across rect
mov si,StartX
cmp cx,si
jle @@FillDone ;skip if 0 or negative width
dec cx
and si,not 011b
sub cx,si
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one byte to draw
and bh,bl ;there's only one byte, so combine the left
; and right edge clip masks
@@MasksSet:
mov si,EndY
sub si,StartY ;BX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov ah,byte ptr Color ;color with which to fill
mov bp,_Virtual_Width_Addr ;stack frame isn't needed any more
sub bp,cx ;distance from end of one scan line to start
dec bp ; of next
@@FillRowsLoop:
push cx ;remember width in addresses - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the left edge
dec cx ;count off left edge byte
js @@FillLoopBottom ;that's the only byte
jz @@DoRightEdge ;there are only two bytes
mov al,00fh ;middle addresses are drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
mov al,ah ;put color in AL
rep stosb ;draw the middle addresses four pixels apiece
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the right edge
@@FillLoopBottom:
add di,bp ;point to the start of the next scan line of
; the rectangle
pop cx ;retrieve width in addresses - 1
dec si ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
pop ds
pop di
pop si
pop bp
ret
_RectangleFillClip endp
;----------------------------------------------------------------------------
; void RectangleFillPattern(int StartX, int StartY, int EndX, int EndY, PATTERN);
public _RectangleFillPattern
_RectangleFillPattern proc far
ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Pattern:DWORD
LOCAL NextScanOffset:WORD, RectAddrWidth:WORD, Height:WORD = LocalStack
push bp
mov bp,sp
sub sp,LocalStack
push si
push di
push ds
cld
mov ax,_ModeX_Segment ;point ES to display memory
mov es,ax
;copy pattern to display memory buffer
; mov si,Pattern ;point to pattern to fill with
mov di,_Pattern_Offset ;point ES:DI to pattern buffer
lds si,Pattern
mov dx,SC_INDEX ;point Sequence Controller Index to
mov al,MAP_MASK ; Map Mask
out dx,al
inc dx ;point to SC Data register
mov cx,4 ;4 pixel quadruplets in pattern
@@DownloadPatternLoop:
mov al,1 ;
out dx,al ;select plane 0 for writes
movsb ;copy over next plane 0 pattern pixel
dec di ;stay at same address for next plane
mov al,2 ;
out dx,al ;select plane 1 for writes
movsb ;copy over next plane 1 pattern pixel
dec di ;stay at same address for next plane
mov al,4 ;
out dx,al ;select plane 2 for writes
movsb ;copy over next plane 2 pattern pixel
dec di ;stay at same address for next plane
mov al,8 ;
out dx,al ;select plane 3 for writes
movsb ;copy over next plane 3 pattern pixel
; and advance address
loop @@DownloadPatternLoop
mov ax, @data
mov ds,ax
mov dx,GC_INDEX ;set the bit mask to select all bits
mov ax,00000h+BIT_MASK ; from the latches and none from
out dx,ax ; the CPU, so that we can write the
; latch contents directly to memory
mov ax,StartY ;top rectangle scan line
mov si,ax
and si,011b ;top rect scan line modulo 4
add si,_Pattern_Offset ;point to pattern scan line that
; maps to top line of rect to draw
mov dx,_Virtual_Width_Addr
mul dx ;offset in page of top rectangle scan line
mov di,StartX
mov bx,di
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,_Display_Offset ;offset of first rectangle pixel in
; display memory
and bx,0003h ;look up left edge plane mask
mov ah,LeftClipPlaneMask[bx] ; to clip
mov bx,EndX
and bx,0003h ;look up right edge plane
mov al,RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,EndX ;calculate # of addresses across rect
mov ax,StartX
cmp cx,ax
jle @@FillDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one pixel to draw
and bh,bl ;there's only one pixel, so combine the left
; and right edge clip masks
@@MasksSet:
mov ax,EndY
sub ax,StartY ;AX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov Height,ax
mov ax,_Virtual_Width_Addr
sub ax,cx ;distance from end of one scan line to start
dec ax ; of next
mov NextScanOffset,ax
mov RectAddrWidth,cx ;remember width in addresses - 1
mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
; (SC Index still points to Map Mask)
@@FillRowsLoop:
mov cx,RectAddrWidth ;width across - 1
mov al,es:[si] ;read display memory to latch this scan
; line's pattern
inc si ;point to the next pattern scan line, wrapping
jnz short @@NoWrap ; back to the start of the pattern if
sub si,4 ; we've run off the end
@@NoWrap:
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
stosb ;draw the left edge (pixels come from latches;
; value written by CPU doesn't matter)
dec cx ;count off left edge address
js @@FillLoopBottom ;that's the only address
jz @@DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses are drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
rep stosb ;draw the middle addresses four pixels apiece
; (from latches; value written doesn't matter)
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
stosb ;draw the right edge (from latches; value
; written doesn't matter)
@@FillLoopBottom:
add di,NextScanOffset ;point to the start of the next scan
; line of the rectangle
dec word ptr Height ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop ds
pop di
pop si
mov sp,bp
pop bp
ret
_RectangleFillPattern endp
;----------------------------------------------------------------------------
; void RectangleFillPatternClip(int StartX, int StartY, int EndX, int EndY, PATTERN);
public _RectangleFillPatternClip
_RectangleFillPatternClip proc far
ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Pattern:DWORD
LOCAL NextScanOffset:WORD, RectAddrWidth:WORD, Height:WORD = LocalStack
push bp
mov bp,sp
sub sp,LocalStack
push si
push di
push ds
; clip it
; yeah, it's may be kinda cheezy, but it's still fairly quick
; (plus, it took about 5min :-])
@@_ClipLeft:
mov ax, StartX
cmp ax, _ClipLeft
jg @@_ClipRight
mov ax, _ClipLeft
mov StartX,ax
@@_ClipRight:
mov ax, EndX
cmp ax, _ClipRight
jle @@_ClipTop
mov ax, _ClipRight
mov EndX, ax
@@_ClipTop:
mov ax, StartY
cmp ax, _ClipTop
jg @@_ClipBottom
mov ax, _ClipTop
mov StartY, ax
@@_ClipBottom:
mov ax, EndY
cmp ax, _ClipBottom
jle @@ClipDone
mov ax, _ClipBottom
mov EndY, ax
@@ClipDone:
cld
mov ax,_ModeX_Segment ;point ES to display memory
mov es,ax
;copy pattern to display memory buffer
; mov si,Pattern ;point to pattern to fill with
mov di,_Pattern_Offset ;point ES:DI to pattern buffer
lds si,Pattern
mov dx,SC_INDEX ;point Sequence Controller Index to
mov al,MAP_MASK ; Map Mask
out dx,al
inc dx ;point to SC Data register
mov cx,4 ;4 pixel quadruplets in pattern
@@DownloadPatternLoop:
mov al,1 ;
out dx,al ;select plane 0 for writes
movsb ;copy over next plane 0 pattern pixel
dec di ;stay at same address for next plane
mov al,2 ;
out dx,al ;select plane 1 for writes
movsb ;copy over next plane 1 pattern pixel
dec di ;stay at same address for next plane
mov al,4 ;
out dx,al ;select plane 2 for writes
movsb ;copy over next plane 2 pattern pixel
dec di ;stay at same address for next plane
mov al,8 ;
out dx,al ;select plane 3 for writes
movsb ;copy over next plane 3 pattern pixel
; and advance address
loop @@DownloadPatternLoop
mov ax, @data
mov ds,ax
mov dx,GC_INDEX ;set the bit mask to select all bits
mov ax,00000h+BIT_MASK ; from the latches and none from
out dx,ax ; the CPU, so that we can write the
; latch contents directly to memory
mov ax,StartY ;top rectangle scan line
mov si,ax
and si,011b ;top rect scan line modulo 4
add si,_Pattern_Offset ;point to pattern scan line that
; maps to top line of rect to draw
mov dx,_Virtual_Width_Addr
mul dx ;offset in page of top rectangle scan line
mov di,StartX
mov bx,di
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,_Display_Offset ;offset of first rectangle pixel in
; display memory
and bx,0003h ;look up left edge plane mask
mov ah,LeftClipPlaneMask[bx] ; to clip
mov bx,EndX
and bx,0003h ;look up right edge plane
mov al,RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,EndX ;calculate # of addresses across rect
mov ax,StartX
cmp cx,ax
jle @@FillDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one pixel to draw
and bh,bl ;there's only one pixel, so combine the left
; and right edge clip masks
@@MasksSet:
mov ax,EndY
sub ax,StartY ;AX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov Height,ax
mov ax,_Virtual_Width_Addr
sub ax,cx ;distance from end of one scan line to start
dec ax ; of next
mov NextScanOffset,ax
mov RectAddrWidth,cx ;remember width in addresses - 1
mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
; (SC Index still points to Map Mask)
@@FillRowsLoop:
mov cx,RectAddrWidth ;width across - 1
mov al,es:[si] ;read display memory to latch this scan
; line's pattern
inc si ;point to the next pattern scan line, wrapping
jnz short @@NoWrap ; back to the start of the pattern if
sub si,4 ; we've run off the end
@@NoWrap:
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
stosb ;draw the left edge (pixels come from latches;
; value written by CPU doesn't matter)
dec cx ;count off left edge address
js @@FillLoopBottom ;that's the only address
jz @@DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses are drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
rep stosb ;draw the middle addresses four pixels apiece
; (from latches; value written doesn't matter)
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
stosb ;draw the right edge (from latches; value
; written doesn't matter)
@@FillLoopBottom:
add di,NextScanOffset ;point to the start of the next scan
; line of the rectangle
dec word ptr Height ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop ds
pop di
pop si
mov sp,bp
pop bp
ret
_RectangleFillPatternClip endp
;----------------------------------------------------------------------------
;void ClearClipPort() {
; RectangleFill(ClipLeft, ClipTop, ClipRight, ClipBottom);
;}
public _ClearClipPort
_ClearClipPort proc
push ds
mov ax,@data
mov ds,ax
xor ax,ax
push ax ;push the color (black)
mov ax,_ClipBottom
push ax
mov ax,_ClipRight
dec ax
push ax
mov ax,_ClipTop
push ax
mov ax,_ClipLeft
push ax
call _RectangleFillAligned
pop ax
pop ax
pop ax
pop ax
pop ax
pop ds
ret
_ClearClipPort endp
;----------------------------------------------------------------------------
;void ClearVirtualPort() {
; RectangleFill(0, 0, Virtual_Width, Virtual_Height, BLACK);
;}
public _ClearVirtualPort
_ClearVirtualPort proc
push ds
mov ax,@data
mov ds,ax
xor ax,ax
push ax ;push color
mov bx,_Virtual_Height_Pix
push bx
mov bx,_Virtual_Width_Pix
dec bx
push bx
push ax
push ax
call _RectangleFillAligned
pop ax
pop ax
pop ax
pop ax
pop ax
pop ds
ret
_ClearVirtualPort endp
;----------------------------------------------------------------------------
END